/*
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *    2011 year
 *    Author: Michael Khromov aka MikeDM (Mike D'Morto)
 *    E-Mail: mikedmorto@gmail.com
 */


/*
Плагин авторизации пользователя. это стандартный плагин авторизующий
комбинацией логин + пароль, данные для авторизации хранятся в базе данных
в более серьезных реализациях такие вещи дублируют или разделяют и выносят
на специальные выносные устройства. для этого и существуют эти плагины


есть два режима работы данного плагина, 1 показ диалога с запросом и анимацией
и 2 это автоматический режим.
Для определиения типа работы своего рода маячком служит наличие непустого параметра login
в строке конфигурации плагина.

параметры конфигурации:
login - собственно логин для автовхода
pass - пароль для входа
*/


#include "liblogon_std.h"
#include <QDebug>

bool Liblogon_std::init(const QStringList &cfg, const QString &lng){
    // подключаем перевод.
    QTranslator * trans = new QTranslator();
    if(trans->load(QString("%1/%2/%3.qm").arg(LANG_PREFIX).arg(PLUGIN_NAME).arg(lng))){
            QCoreApplication::installTranslator(trans);
            emit this->sigPutLog(PLUGIN_NAME,3,QString(tr("Debug: success translate %1")).arg(lng));
        }else{
            emit this->sigPutLog(PLUGIN_NAME,1,QString("fail translate %1").arg(lng));
        }
    emit this->sigPutLog(PLUGIN_NAME,2,tr("Info: start init"));
    // парсим параметры инициализации
    emit this->sigPutLog(PLUGIN_NAME,3,tr("Debug: parsing config string"));
    // ищем наличие login
    for(int i = 1 ; i < cfg.size() ; i++){
        QStringList tt = cfg.at(i).split("=");
        if(tt.at(0)=="login"){
                if(tt.size() > 1){
                    emit this->sigPutLog(PLUGIN_NAME,3,tr("Debug: login found"));
                    this->login=cfg.at(i).split("=").at(1);
                }
        }
    }
    // ищем наличие pass
    for(int i = 1 ; i < cfg.size() ; i++){
        QStringList tt = cfg.at(i).split("=");
        if(tt.at(0)=="pass"){
                if(tt.size() > 1){
                    emit this->sigPutLog(PLUGIN_NAME,3,tr("Debug: pass found"));
                    this->pass=cfg.at(i).split("=").at(1);
                }
        }
    }
    this->autoEnter=false;
    // подготавливаем диалог
    this->dia = new LogonDialog();
    // завязываем механизмы взаимодействия диалога
    connect(this->dia,SIGNAL(sigLoginPass(QString,QString)),this,SLOT(slotDiaLoginPass(QString,QString)));
    connect(this,SIGNAL(sigErrorDia(QString)),this->dia,SLOT(slotError(QString)));
    /*
      поскольку диалог не может взаимодействовать с базой напрямую используя
      механизмы плагина, то он должен подать сигнал о начале проверки пары
      логин пароль и каким то образом получит ответ об ошибке, ибо при верном логине и пароле
      диалог нужно будет просто закрыть и продолжить работу уже ядру

    */

    emit this->sigPutLog(PLUGIN_NAME,3,tr("Debug: success init."));
    return true;
}

QString Liblogon_std::getlastError(){
    return this->lastError;
}

bool Liblogon_std::exec(){
    if(this->login.isEmpty()){
        // логин изначально пуст, вызываем красивый диалог и требуем авторизации

        return this->dia->exec();
    }else{
        // опапа что то есть, пробуем автовход
        this->autoEnter=true;
        QStringList aa;
        aa.append(this->login);
        aa.append(this->pass);
        emit this->sigQuery(PLUGIN_NAME,"logon",aa);
        // ждем флагов окончания
        this->isAErr=true;
        this->isAFin=false;
        for(;;){
            usleep(100); // шобе не хавало проц
            QApplication::processEvents();
            if(this->isAFin){
                return this->isAErr;
            }
        }
    }

}

void Liblogon_std::slotDiaLoginPass(const QString &login, const QString &pass){
    // пришел запрос на проверку пары логина и пароля от диалога.
    // генерируем сигнал в плагину бд
    QStringList aa;
    aa.append(login);
    this->login=login;
    aa.append(pass);
    emit this->sigQuery(PLUGIN_NAME,"logon",aa);
}

void Liblogon_std::slotDbError(const QString &pl_name, const QString &errtext){
    // прилетело ошибко от базы данных.
    // глядим, нам ли ? -=) а то всякое бывает мать их
    if(pl_name == PLUGIN_NAME){
        if(this->autoEnter){
            this->lastError=errtext;
            this->isAErr=false;
            this->isAFin=true;
        }else{
            // стучимся в диалог с докладом об ошибке
            emit this->sigErrorDia(errtext);
        }
    }

}

void Liblogon_std::slotDbResult(const QString &pl_name, int id, Mdata *data){
    // ответ от базы вернулся, смотрим нам или нет, хотя плагины могут глядеть все
    // результаты, не рекомендуется хватать чужие, тк совместный доступ одновременный
    // может повлечь за собой кучу подземных стуков, посему возмите за правило не трогать
    // чужой результат.
    if(pl_name == PLUGIN_NAME){
        // нам прилетело, глядим чего прилетело -)
        if(!data->next()){
            // охтыжептваюмать, результата нема, по идее это ошибка фатальна,
            // тут можно и завершение работы с фанфарами устроить.
            // но мы люди воспитанный и постучимся в диалог с ошибкой
            emit this->sigPutLog(PLUGIN_NAME,2,tr("Info: OMG returned data is null"));
            emit this->sigErrorDia(tr(" OMG returned data is null"));
        }else{
            // результат вроде как есть, вынимаем
            QStringList ret=data->getData();
            if(!ret.size()==1){
                // чет дофига вернулось. ругаемся
                emit this->sigPutLog(PLUGIN_NAME,2,tr("Info: OMG returned data is failure"));
                emit this->sigErrorDia(tr(" OMG returned data is failure"));
            }else{
                // ну неужели все верно -)))))
                // ан нет, надо проверить что вернулось, если еденичко то пользователь с таким паролем есть
                // если нулик или еще какая херня больше 1 то либо такого нет либо их несколько ... что тоже косяк.
                QString rr=ret.at(0);

                if(rr != "0" and rr != "1"){
                    // вот и беда
                    emit this->sigPutLog(PLUGIN_NAME,2,tr("Info: OMG dublicated login"));
                    emit this->sigErrorDia(tr(" OMG dublicated login"));
                }else{
                    if(rr=="0"){
                        // логин пароль не верен
                        emit this->sigPutLog(PLUGIN_NAME,2,tr("Info: not logged in - login or password is incorrect."));
                        if(this->autoEnter){
                            this->lastError=tr(" not logged in - login or password is incorrect.");
                            this->isAErr=false;
                            this->isAFin=true;
                        }else{
                            emit this->sigErrorDia(tr(" not logged in - login or password is incorrect."));
                        }
                    }else{
                        // уряяя пользователь есть и его пускают
                        emit this->sigPutLog(PLUGIN_NAME,3,tr("Debug: user enterned"));
                        if(this->autoEnter){
                            this->isAFin=true;
                        }else{
                            this->dia->logonOK();
                        }
                    }
                }
            }
        }
        // подчищаем данные
        this->sigFreeRes(id);
    }
}

QString Liblogon_std::getUserName(){
    return this->login;
}

Q_EXPORT_PLUGIN2(iLogon,Liblogon_std)
